package com.eliza.v.http.base

import com.eliza.v.http.VertxTools
import io.vertx.core.AbstractVerticle
import io.vertx.core.Promise
import io.vertx.core.http.HttpMethod
import io.vertx.core.json.JsonArray
import io.vertx.ext.web.Router.router

/*
* 路由匹配失败
    如果没有任何路由匹配任何特定请求，Vert.x-Web 将根据匹配失败发出错误信号：

    404 如果没有路由匹配路径

    405 如果路由匹配路径但不匹配 HTTP 方法

    406 如果路由匹配路径和方法，但无法提供内容类型匹配Accept标头的响应

    415 如果路由匹配路径和方法但它不能接受 Content-type

    400 如果路由匹配路径和方法但它不能接受空的主体
* */
/*-*- coding:utf-8 -*-
 * @Author  : debi
 * @Time    : 2/1/22
 * @Software: IntelliJ IDEA
 */
class ContextData : AbstractVerticle() {
    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            VertxTools.runVertical(ContextData::class.java)
        }
    }
    override fun start(startPromise: Promise<Void>?) {
        super.start(startPromise)
//        putGet() /err
//        metaData()
//        redirect()
//        helperFunction()
//        reRouting() //err
        acceptLanguage()
    }

    /** 上下文数据*/

    private fun putGet() {
        val router = router(vertx)
        router.get("/some")
            .handler { ctx ->
                ctx.put("foo", "bar")
                ctx.next()
            }

        router["/some/path/other"].handler { ctx ->
            val bar: String = ctx["foo"]
            println(bar)
            ctx.response().end(bar)
        }

        VertxTools.result(vertx, this, "putGet", router, 8080)

    }

    /** 元数据*/
    private fun metaData() {
        val router = router(vertx)
/*
* 虽然上下文允许您在请求-响应生命周期中存储数据，但有时让运行时元数据可用很重要。
* 例如，构建 API 文档，或为给定路由保存特定配置。
    元数据功能与上下文数据类似。您可以访问馆藏，
    * 也可以使用在和接口Map上定义的专用 getter 和 setter ：RouterRoute*/
        router
            .route("/metaData").method(HttpMethod.POST)
            .putMetadata("metadata-key", "123")
            .handler { ctx ->
                val route = ctx.currentRoute()
                val value = route.getMetadata<String>("metadata-key") // 123

                ctx.end(value)
            }

        VertxTools.result(vertx, this, "metaData", router, 8080)

    }

    /** 辅助函数*/
    /*
    * 辅助函数
    虽然路由上下文将允许您访问底层请求和响应对象，但有时如果提供一些快捷方式来帮助完成常见任务，
    * 它会更有效率。上下文中存在一些帮助程序以促进此任务。
    提供“附件”，附件是一个响应，它将触发浏览器在配置为处理特定 mime 类型的操作系统应用程序上打开响应
    * */
    private fun helperFunction() {
        val router = router(vertx)

        router
            .route("/helperFunction")
            .handler { rc ->
                //  向客户端发送 JSON 响应：
//                rc.json(JsonObject().put("hello", "vert.x"))
                // also applies to arrays
                rc.json(JsonArray().add("vertx").add("web"))

                //简单的内容类型检查
                println(rc.`is`("html")) // => false
            }
        /*
                  打开pdf
              .handler { rc ->
                  rc.attachment("weekly-report.pdf")
  //                rc.end(pdfBuffer);
              }*/

        VertxTools.result(vertx, this, "helperFunction", router, 8080)

    }

    private fun redirect() {
        val router = router(vertx)

        router
            .route("/redirect")
            .handler { rc ->
//                重定向
                rc.redirect("https://shouku123.com/Elizabevil")
            }
        VertxTools.result(vertx, this, "redirect", router, 8080)

    }

    /** 重返路由*/
    private fun reRouting() {
        /*
        * ，所有路由机制都允许您以顺序方式处理您的请求，但是有时您可能想要返回。
        * 由于上下文没有公开任何关于前一个或下一个处理程序的信息，
        * 主要是因为这些信息是动态的，所以有一种方法可以从当前路由器的开始处重新启动整个路由。*/
        val router = router(vertx)
        router.get("/reRouting/A").handler { ctx ->
            println("/reRouting/A")
            ctx.next()
        }

        router["/reRouting/B"]
            .handler { ctx ->
                ctx.put("foo", "bar")
                ctx.response().setChunked(true).write("foo")

                println("/reRouting/B")
                ctx.response().end()
            }

        router["/reRouting/C"]
            .handler { ctx ->
                println("/reRouting/C")

                ctx.reroute("/reRouting/B")
            }

        VertxTools.result(vertx, this, "reRouting", router, 8080)


    }

    /** Accept-Language*/
    private fun acceptLanguage() {
        val router = router(vertx)
        router["/acceptLanguage"].handler { ctx ->

            for (language in ctx.acceptableLanguages()) {
                when (language.tag()) {
                    "en" -> {
                        ctx.response().end("Hello!")
                        return@handler
                    }
                    "fr" -> {
                        ctx.response().end("Bonjour!")
                        return@handler
                    }
                    "pt" -> {
                        ctx.response().end("Olá!")
                        return@handler
                    }
                    "es" -> {
                        ctx.response().end("Hola!")
                        return@handler
                    }
                }
            }
            // we do not know the user language so lets just inform that back:
            ctx.response().end("Sorry we don't speak: " + ctx.preferredLanguage())
        }

        VertxTools.result(vertx, this, "acceptLanguage", router, 8080)

    }

}